package com.zxjbyte.yiyi.framework.common.util;

import cn.hutool.extra.spring.SpringUtil;
import com.google.common.eventbus.EventBus;
import com.zxjbyte.yiyi.framework.common.core.eventbus.AsyncEventBusService;
import com.zxjbyte.yiyi.framework.common.core.eventbus.EventBusService;
import lombok.experimental.UtilityClass;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

/**
 * 事件总线工具类
 *
 * @Author zhangxingjia
 * @Date 2025/4/9 14:53
 * @Version: 1.0
 */
@UtilityClass
public class EventBusUtil {

    private static class AsyncHolder {
        static final AsyncEventBusService INSTANCE = SpringUtil.getBean(AsyncEventBusService.class);
    }

    private static class SyncHolder {
        static final EventBusService INSTANCE = SpringUtil.getBean(EventBusService.class);
    }

    /**
     * 异步发送事件
     * @param event 事件对象
     */
    public void asyncPublishEvent(Object event){
        ValidationUtil.assertNotNull(event, "Event");
        AsyncHolder.INSTANCE.post(event);
    }

    /**
     * 同步发送事件
     * @param event 事件对象
     */
    public void publishEvent(Object event){
        ValidationUtil.assertNotNull(event, "Event");
        SyncHolder.INSTANCE.post(event);
    }


    /**
     * (此方法不建议使用，效率相对较低)
     * 
     * 智能发送事件，根据订阅者的注解自动判断同步或异步
     * @param event 事件对象
     */
    public void smartPublishEvent(Object event) {
        ValidationUtil.assertNotNull(event, "Event");
        // 获取事件类型
        Class<?> eventType = event.getClass();
        // 检查是否有需要同步处理的订阅者
        boolean needSync = hasSyncSubscriber(eventType);
        if (needSync) {
            SyncHolder.INSTANCE.post(event);
        } else {
            AsyncHolder.INSTANCE.post(event);
        }
    }

    /**
     * 检查是否有订阅者要求同步处理
     * @param eventType 事件类型
     * @return 是否需要同步处理
     */
    private boolean hasSyncSubscriber(Class<?> eventType) {
        // 获取同步事件总线的订阅者
        try {
            // 使用反射获取EventBus的subscribers
            Field subscribersField = EventBus.class.getDeclaredField("subscribers");
            subscribersField.setAccessible(true);

            // 获取同步总线的订阅者映射
            Map<Class<?>, Set<Object>> syncSubscribers = getSubscribersMap(SyncHolder.INSTANCE.getEventBus(), subscribersField);

            // 只要同步总线有订阅者，就返回 true
            return syncSubscribers.containsKey(eventType);
        } catch (Exception e) {
            // 反射失败，保守处理，使用同步方式
            return true;
        }
    }


    /**
     * 获取EventBus的订阅者映射
     */
    private Map<Class<?>, Set<Object>> getSubscribersMap(EventBus eventBus, Field subscribersField) throws IllegalAccessException {
        Object subscribers = subscribersField.get(eventBus);

        // Guava EventBus的subscribers是一个SubscriberRegistry
        Class<?> subscriberRegistryClass = subscribers.getClass();
        try {
            Field subscriberMapField = subscriberRegistryClass.getDeclaredField("subscribers");
            subscriberMapField.setAccessible(true);
            return (Map<Class<?>, Set<Object>>) subscriberMapField.get(subscribers);
        } catch (Exception e) {
            throw new IllegalStateException("Failed to get subscribers from EventBus", e);
        }
    }

}
